﻿using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;

namespace GISCommon.Business
{
    public class MapIndexHelper
    {
        #region 变量定义
        private AxMapControl m_pIndexMapControl;
        private AxMapControl m_pMainMapControl;

        private int m_X0 = 0;
        private int m_Y0 = 0;

        private ESRI.ArcGIS.Geometry.IPoint m_newCenterPT = new ESRI.ArcGIS.Geometry.PointClass();

        private bool m_blnMouseDown = false;
        private bool m_blnMouseMove = false;

        private float m_ZoomOutFactor = 3;
        #endregion

        #region 对外函数
        /// <summary>
        /// 描述：类的初始化
        /// </summary>
        /// <param name="vIndexMC">索引地图控件</param>
        /// <param name="vMainMC">主地图控件</param>
        public void Initial(AxMapControl vIndexMC, AxMapControl vMainMC)
        {
            try
            {
                SysCommon.Global.mainLog.Debug("开始调用Initial函数");
                m_pIndexMapControl = vIndexMC;
                m_pMainMapControl = vMainMC;

                //事件声明
                m_pIndexMapControl.OnMouseDown +=
                    new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(
                        m_pIndexMapControl_OnMouseDown);
                m_pIndexMapControl.OnMouseMove +=
                    new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseMoveEventHandler(
                        m_pIndexMapControl_OnMouseMove);
                m_pIndexMapControl.OnMouseUp +=
                    new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseUpEventHandler(m_pIndexMapControl_OnMouseUp);
                m_pMainMapControl.OnAfterDraw +=
                    new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnAfterDrawEventHandler(m_pMainMapControl_OnAfterDraw);
                m_pMainMapControl.OnExtentUpdated +=
                    new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnExtentUpdatedEventHandler(
                        m_pMainMapControl_OnExtentUpdated);
                m_pMainMapControl.Resize += new System.EventHandler(this.m_pMainMapControl_Resize);

                ZoomIndexMap(m_pMainMapControl.Width, m_pMainMapControl.Height);

                SysCommon.Global.mainLog.Debug("结束调用Initial函数");
            }
            catch(Exception ex)
            {
                SysCommon.Global.mainLog.Error("Initial函数调用出错。",ex);
            }
        }
        #endregion

        #region 私有函数
        /// <summary>
        /// 描述：响应主地图的缩放等变化事件处理
        /// </summary>
        /// <param name="mWidth">主地图控件的宽</param>
        /// <param name="mHeight">主地图控件的长</param>
        private void OnAfterDraw(int mWidth, int mHeight)
        {

            ZoomIndexMap(mWidth, mHeight);
        }

        /// <summary>
        /// 描述：响应索引图的鼠标移动事件处理

        /// </summary>
        /// <param name="x">鼠标的当前点X坐标</param>
        /// <param name="y">鼠标的当前点Y坐标</param>
        private void OnMouseMove(double x, double y)
        {
            ChangeMouseIcon(x, y);
            ClearElements();
            DrawCenterRectangle(m_pMainMapControl.Width,m_pMainMapControl.Height);
            DrawNewRectangle(x, y);
        }

        /// <summary>
        /// 描述：响应索引图的鼠标按下事件处理

        /// </summary>
        /// <param name="x">鼠标的当前点X坐标</param>
        /// <param name="y">鼠标的当前点Y坐标</param>
        private void OnMouseDown(double x, double y)
        {
            ESRI.ArcGIS.Geometry.IPoint pPoint = new ESRI.ArcGIS.Geometry.PointClass();
            pPoint.PutCoords(x, y);
            m_pMainMapControl.FromMapPoint(pPoint, ref m_X0, ref m_Y0);
        }

        /// <summary>
        /// 描述：响应索引图的鼠标弹起事件处理

        /// </summary>
        private void OnMouseUp()
        {
            m_pMainMapControl.CenterAt(m_newCenterPT);
        }
        

        
        /// <summary>
        /// 描述：根据主地图的变化调整索引图的尺寸

        /// </summary>
        /// <param name="mWidth">主地图控件的宽</param>
        /// <param name="mHeight">主地图控件的长</param>
        private void ZoomIndexMap(int mWidth, int mHeight)
        {
            try
            {
                //计算主地图控件当前的地图范围
                //设置地图控件变量的新尺寸
                m_pMainMapControl.Width = mWidth;
                m_pMainMapControl.Height = mHeight;
                //计算其当前视图范围

                int mXi = 0;
                int mXa = mWidth;
                int mYi = mHeight;
                int mYa = 0;
                //转换成地图坐标范围

                ESRI.ArcGIS.Geometry.IPoint pMII = m_pMainMapControl.ToMapPoint(mXi, mYi);
                ESRI.ArcGIS.Geometry.IPoint pMAA = m_pMainMapControl.ToMapPoint(mXa, mYa);
                ESRI.ArcGIS.Geometry.IEnvelope pMEnvelope = new ESRI.ArcGIS.Geometry.EnvelopeClass();
                pMEnvelope.PutCoords(pMII.X, pMII.Y, pMAA.X, pMAA.Y);
                //设置索引地图的范围

                pMEnvelope.Expand(m_ZoomOutFactor, m_ZoomOutFactor, true);
                m_pIndexMapControl.ActiveView.ScreenDisplay.DisplayTransformation.Bounds = pMEnvelope;
                m_pIndexMapControl.ActiveView.Refresh();
                //把索引图移到主地图中心

                double dblX = (pMII.X + pMAA.X) / 2;
                double dblY = (pMII.Y + pMAA.Y) / 2;
                ESRI.ArcGIS.Geometry.IPoint pCenterPoint = new ESRI.ArcGIS.Geometry.PointClass();
                pCenterPoint.PutCoords(dblX, dblY);
                m_pIndexMapControl.CenterAt(pCenterPoint);
                //画矩形框
                ClearElements();
                DrawCenterRectangle(mWidth, mHeight);
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用ZoomIndexMap(int mWidth, int mHeight)出错", ex);
            }
        }

        /// <summary>
        /// 描述：清除索引图上的元素
        /// </summary>
        private void ClearElements()
        {
            try
            {
                m_pIndexMapControl.ActiveView.GraphicsContainer.DeleteAllElements();
                esriViewDrawPhase p = esriViewDrawPhase.esriViewGraphics;
                m_pIndexMapControl.Refresh(p, null, null);
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用ClearElements()出错", ex);
            }
        }

        /// <summary>
        /// 描述：画中心矩形框

        /// </summary>
        /// <param name="mWidth">主地图控件的宽</param>
        /// <param name="mHeight">主地图控件的长</param>
        private void DrawCenterRectangle(int mWidth, int mHeight)
        {
            try
            {
                int mXi = 0;
                int mXa = mWidth;
                int mYi = mHeight;
                int mYa = 0;

                ESRI.ArcGIS.Geometry.IPoint pII = m_pMainMapControl.ToMapPoint(mXi, mYi);
                ESRI.ArcGIS.Geometry.IPoint pAI = m_pMainMapControl.ToMapPoint(mXa, mYi);
                ESRI.ArcGIS.Geometry.IPoint pAA = m_pMainMapControl.ToMapPoint(mXa, mYa);
                ESRI.ArcGIS.Geometry.IPoint pIA = m_pMainMapControl.ToMapPoint(mXi, mYa);

                ESRI.ArcGIS.Geometry.IPointCollection pPointColl = new ESRI.ArcGIS.Geometry.PolylineClass();

                object ep = System.Reflection.Missing.Value;
                pPointColl.AddPoint(pII, ref ep, ref ep);
                pPointColl.AddPoint(pAI, ref ep, ref ep);
                pPointColl.AddPoint(pAA, ref ep, ref ep);
                pPointColl.AddPoint(pIA, ref ep, ref ep);
                pPointColl.AddPoint(pII, ref ep, ref ep);

                //矩形框多边形
                ESRI.ArcGIS.Geometry.IPolyline pPolyline = (ESRI.ArcGIS.Geometry.IPolyline)pPointColl;
                DrawPolyline(pPolyline, true);
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用DrawCenterRectangle(int mWidth, int mHeight)出错", ex);
            }
        }

        /// <summary>
        /// 描述：鼠标移动时在索引图上画新矩形框
        /// </summary>
        /// <param name="x">鼠标所在点的X坐标</param>
        /// <param name="y">鼠标所在点的Y坐标</param>
        private void DrawNewRectangle(double x, double y)
        {
            try
            {
                //先把点坐标转化成窗体像数位置点

                ESRI.ArcGIS.Geometry.IPoint pPoint = new ESRI.ArcGIS.Geometry.PointClass();
                pPoint.PutCoords(x, y);
                int Xp = 0;
                int Yp = 0;
                m_pMainMapControl.FromMapPoint(pPoint, ref Xp, ref Yp);
                //计算主地图控件范围的坐标点

                int mXi = 0;
                int mXa = m_pMainMapControl.Width;
                int mYi = m_pMainMapControl.Height;
                int mYa = 0;
                //计算新位置下的矩形边框端点

                int Xi = mXi + Xp - m_X0;
                int Yi = mYi + Yp - m_Y0;
                int Xa = mXa + Xp - m_X0;
                int Ya = mYa + Yp - m_Y0;
                //转换成地图坐标

                ESRI.ArcGIS.Geometry.IPoint pII = m_pMainMapControl.ToMapPoint(Xi, Yi);
                ESRI.ArcGIS.Geometry.IPoint pAI = m_pMainMapControl.ToMapPoint(Xa, Yi);
                ESRI.ArcGIS.Geometry.IPoint pAA = m_pMainMapControl.ToMapPoint(Xa, Ya);
                ESRI.ArcGIS.Geometry.IPoint pIA = m_pMainMapControl.ToMapPoint(Xi, Ya);
                //生成线对象

                ESRI.ArcGIS.Geometry.IPointCollection pPointColl = new ESRI.ArcGIS.Geometry.PolylineClass();
                object ep = System.Reflection.Missing.Value;
                pPointColl.AddPoint(pII, ref ep, ref ep);
                pPointColl.AddPoint(pAI, ref ep, ref ep);
                pPointColl.AddPoint(pAA, ref ep, ref ep);
                pPointColl.AddPoint(pIA, ref ep, ref ep);
                pPointColl.AddPoint(pII, ref ep, ref ep);
                ESRI.ArcGIS.Geometry.IPolyline pPolyline = (ESRI.ArcGIS.Geometry.IPolyline)pPointColl;
                //画新矩形
                DrawPolyline(pPolyline, false);
                //计算新位置下的矩形边框中心点
                int CX = (Xi + Xa) / 2;
                int CY = (Yi + Ya) / 2;
                m_newCenterPT = m_pMainMapControl.ToMapPoint(CX, CY);
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用DrawNewRectangle(double x, double y)出错", ex);
            }
        }

        /// <summary>
        /// 描述：画多边形

        /// </summary>
        /// <param name="pPolyline">多边形</param>
        /// <param name="IsCenterPolyline">是否屏幕中心点的多边形</param>
        private void DrawPolyline(ESRI.ArcGIS.Geometry.IPolyline pPolyline,bool IsCenterPolyline)
        {
            try
            {
                //画线
                IElement pElement;
                ILineElement pPLineElement;
                IGraphicsContainer pGraCon;

                pGraCon = (IGraphicsContainer)m_pIndexMapControl.ActiveView.GraphicsContainer;

                IRgbColor pRgbColor = (IRgbColor)new RgbColorClass();
                ILineSymbol pSymbol = (ILineSymbol)new SimpleLineSymbolClass();

                if (!IsCenterPolyline)
                    pRgbColor.Blue = 255;
                else
                    pRgbColor.Red = 255;

                pSymbol.Color = pRgbColor;
                pSymbol.Width = 2;

                pPLineElement = (ILineElement)new LineElementClass();
                pPLineElement.Symbol = pSymbol;

                pElement = (IElement)pPLineElement;
                pElement.Geometry = pPolyline;

                pGraCon.AddElement(pElement, 0);

                esriViewDrawPhase Phase = esriViewDrawPhase.esriViewGraphics;
                m_pIndexMapControl.Refresh(Phase, pElement, (object)pPolyline.Envelope);
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用DrawPolyline(ESRI.ArcGIS.Geometry.IPolyline pPolyline,bool IsCenterPolyline)出错", ex);
            }
        }

        /// <summary>
        /// 描述：根据鼠标当前位置改变鼠标的图标
        /// </summary>
        /// <param name="x">鼠标当前点X坐标</param>
        /// <param name="y">鼠标当前点Y坐标</param>
        private void ChangeMouseIcon(double x, double y)
        {
            try
            {
                int Xi = 0;
                int Xa = m_pMainMapControl.Width;
                int Yi = m_pMainMapControl.Height;
                int Ya = 0;

                ESRI.ArcGIS.Geometry.IPoint pII = m_pMainMapControl.ToMapPoint(Xi, Yi);
                ESRI.ArcGIS.Geometry.IPoint pAA = m_pMainMapControl.ToMapPoint(Xa, Ya);

                if (pII.X <= x && x <= pAA.X && pII.Y <= y && y <= pAA.Y)
                {
                    m_pIndexMapControl.MousePointer = esriControlsMousePointer.esriPointerSize;
                }
                else
                {
                    if (!m_blnMouseDown)
                        m_pIndexMapControl.MousePointer = esriControlsMousePointer.esriPointerDefault;
                }
            }
            catch (Exception ex)
            {
                SysCommon.Global.mainLog.Error("调用ChangeMouseIcon(double x, double y)出错", ex);
            }
        }
        #endregion

        #region 处理事件
        private void m_pMainMapControl_OnAfterDraw(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnAfterDrawEvent e)
        {
            //OnAfterDraw(m_pMainMapControl.Width, m_pMainMapControl.Height);
        }

        private void m_pIndexMapControl_OnMouseDown(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent e)
        {
            m_blnMouseDown = true;
            OnMouseDown(e.mapX, e.mapY);
        }

        private void m_pIndexMapControl_OnMouseMove(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseMoveEvent e)
        {
            ChangeMouseIcon(e.mapX, e.mapY);
            if (m_blnMouseDown)
            {
                OnMouseMove(e.mapX, e.mapY);
                m_blnMouseMove = true;
            }
        }

        private void m_pIndexMapControl_OnMouseUp(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseUpEvent e)
        {
            if (m_blnMouseMove)
            {
                OnMouseUp();
                m_blnMouseMove = false;
                m_blnMouseDown = false;
            }
        }

        private void m_pMainMapControl_Resize(object sender, EventArgs e)
        {
            OnAfterDraw(m_pMainMapControl.Width, m_pMainMapControl.Height);
        }

        private void m_pMainMapControl_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
        {
            OnAfterDraw(m_pMainMapControl.Width, m_pMainMapControl.Height);
        }
        #endregion

        #region 属性设置

        /// <summary>
        /// 描述：设置索引图矩形框的比例系数
        /// </summary>
        public float ZoomOutFactor
        {
            get { return m_ZoomOutFactor; }
            set { m_ZoomOutFactor = value; }
        }
        #endregion
    }
}
